home *** CD-ROM | disk | FTP | other *** search
- /*
- * ttcptest.c
- *
- * Small example for a T/TCP-compliant client.
- *
- * This client tries to connect to the auth (identd) port of the
- * specified host using T/TCP. If T/TCP is not supported it falls
- * back to TCP.
- *
- * (C) Copyright 1996,1997 by Nordic Global Inc. All rights reserved.
- * T/TCP code for use with Miami only.
- *
- * 07/30/97: first version
- *
- * 12/28/97: - added support for PPC
- * - added support for protocol-independent hostname lookup
- * (for IPv6 compatibility)
- */
-
- #define __USE_SYSBASE
- #include <proto/exec.h>
- #include <proto/miami.h>
- #include <proto/socket.h>
-
- #include <sys/socket.h>
- #include <netinet/tcp.h>
- #include <dos.h>
- #include <netdb.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
-
-
- struct Library *MiamiBase=0;
-
- static int dottcp=0;
- static int protoind=0;
-
- #define REQUEST "1 : 1\r\n"
-
- void myexit(void) {
- if(MiamiBase) {
- CloseLibrary(MiamiBase);
- MiamiBase=0;
- }
- }
-
- int mybreak(void) {
- myexit();
- return 1;
- }
-
- void get_response(int sockfd,char *buf,int max) {
- int len=0,le;
- while(len<max-1) {
- le=recv(sockfd,buf+len,max-len-1,0);
- if(le==0) {
- buf[len]=0;
- return;
- }
- if(le<0) {
- fprintf(stderr,"recv: error %d\n",Errno());
- exit(10);
- }
- len+=le;
- }
- buf[max-1]=0;
- }
-
- void main(int argc,char **argv) {
- struct hostent *he;
- struct servent *se;
- long sockfd,n=1,err,family,sockettype;
- char buf[256];
- struct sockaddr_in sin;
- struct sockaddr *sa;
- struct addrinfo *addrinfo=0;
-
- if(argc==0)
- exit(0);
- if(argc!=2) {
- fprintf(stderr,"Usage: %s host\n",argv[0]);
- exit(10);
- }
-
- /* install exit and break hooks so MiamiBase gets closed
- in all cases */
-
- atexit(myexit);
-
- #ifndef __PPC__
- /* onbreak() is not supported by SAS/C-PPC yet */
- onbreak(mybreak);
- #endif
-
- /* miami.library versions >= 3 support T/TCP */
-
- if(MiamiBase=OpenLibrary("miami.library",3)) {
- dottcp=1;
-
- /* miami.library versions >= 12 support protocol-
- independent hostname lookup (IPv6 compatible) */
-
- if(MiamiBase->lib_Version>=12)
- protoind=1;
- }
-
-
- /* ---- host name / service stuff */
-
- if(protoind) {
-
- /* new protocol-independent version */
-
- if(getaddrinfo(argv[1],"auth",0,&addrinfo)) {
- fprintf(stderr,"Host `%s' with service `auth' not found\n",argv[1]);
- exit(10);
- }
- family=addrinfo->ai_family;
- sockettype=addrinfo->ai_socktype;
- sa=addrinfo->ai_addr;
- } else {
-
- /* old IPv4-only version */
-
- if(!(he=gethostbyname(argv[1]))) {
- fprintf(stderr,"Host `%s' not found\n",argv[1]);
- exit(10);
- }
- if(!(se=getservbyname("auth","tcp"))) {
- fprintf(stderr,"Service `auth' not found\n");
- exit(10);
- }
- sin.sin_family=family=AF_INET;
- sockettype=SOCK_STREAM;
- sin.sin_len=sizeof(sin);
- memcpy(&sin.sin_addr,he->h_addr,he->h_length);
- sin.sin_port=se->s_port;
- sa=(struct sockaddr *)&sin;
- }
-
- if(0>(sockfd=socket(family,sockettype,0))) {
- fprintf(stderr,"Unable to create socket\n");
- exit(10);
- }
-
- /* ---- start of T/TCP stuff */
- if(dottcp) {
-
- /* The following call is useful if a sendto() may be larger than
- the MSS, to ensure that packets are packed tightly. (If this seems
- strange, that's probably because it is. It has to do with some
- odd quirks in the implementation of sosend() in all BSD-derived
- TCP/IP stacks. Don't ask any questions -- just add this call
- to your program :-)).
-
- HOWEVER: only add the call if you do NOT reuse your TCP connection
- for multiple requests. If you want to transmit multiple pairs of
- "transaction"/"response" across the same TCP link (e.g. HTTP 1.1
- "persistent TCP connections"), then do NOT add the following
- call. */
-
- setsockopt(sockfd,IPPROTO_TCP,TCP_NOPUSH,(char *)&n,sizeof(n));
-
-
- /* Instead of the usual connect() followed by send(), for T/TCP you
- use a sendto() call, as you would for UDP sockets.
-
- If you have a known amount of data to send that you can send in
- a single function call, then you should use one single sendto()
- call with the MSG_EOF flag set, as in this example. This is the
- preferred way to do it, and gives best performance.
-
- If you absolutely need to loop then use a sequence like
-
- sendto(,,,0,,);
- while(!done) {
- send(,,,0);
- }
- send(,,,MSG_EOF);
-
- this means set the MSG_EOF flag in the *last* send() call only.
-
- MSG_EOF performs an implicit shutdown() for one direction of the
- link, improving performance because the shutdown() can be
- piggy-backed on data packets, i.e. no additional packets are
- needed for a shutdown() or CloseSocket() later.
-
- However *do not* use MSG_EOF if you want to re-use your
- connection for subsequent requests (e.g. "persistent TCP
- connections" in HTTP-1.1). */
-
- if(sendto(sockfd,REQUEST,strlen(REQUEST),MSG_EOF,sa,sa->sa_len)
- !=strlen(REQUEST)) {
- if((err=Errno())==ENOTCONN) {
- /* T/TCP failed. Try ordinary TCP */
- dottcp=0;
- } else {
- fprintf(stderr,"sendto: error %d\n",err);
- exit(10);
- }
- }
- }
- /* ---- end of T/TCP stuff */
-
- if(!dottcp) {
- if(connect(sockfd,sa,sa->sa_len)<0) {
- fprintf(stderr,"connect: error %d\n",Errno());
- exit(10);
- }
- if(send(sockfd,REQUEST,strlen(REQUEST),0)!=strlen(REQUEST)) {
- fprintf(stderr,"send: error %d\n",Errno());
- exit(10);
- }
- }
- get_response(sockfd,buf,256);
- puts(buf);
- CloseSocket(sockfd);
- if(addrinfo)
- freeaddrinfo(addrinfo);
- }
-